#ifndef __COMMAND_H_
#define __COMMAND_H_

#include "common.h"
/*********************************************************
**
**Macro Define
**********************************************************/
#define CMD_BUF_SIZE (512)
#define CMD_ARGC_MAX (512)
#define ARG_VAL_BUF_SIZE (32)
#define CMD_NAME_SIZE (32)

extern char cmd_buf[CMD_BUF_SIZE + 1];
extern char args_buf[CMD_BUF_SIZE + 1];

#define MODULE_FLAG "@"

typedef enum _Cmd_res
{
    OK = 0,
    ERR,
    TIME_OUT,
    NF_BB,
    ABORT,
    MISMATCH,
    ARG_ERR,
    UNKNOWN,
}cmd_res;

typedef cmd_res (*tfunc)(int,char **);
typedef void (*terr_proc)(int);

/**
 * \define struct tcmd
 * \indicate one command.
 */
typedef struct _tcmd{
    char *name;
    cmd_res (*func)(int argc,char *argv[]);
    const char *usage;
}tcmd;

/**
 * \define ADD_CMD
 * \add one command.
 */
#define Cmd_Sec __attribute__((section(".sec_cmd")))
#define ADD_CMD(name,func,usage) \
        tcmd _test_cmd_##name Cmd_Sec = {#name,func,usage}

/**
 * \define struct titem
 * \indicate one test item in one module.
 */
typedef struct _titem{
    const char *name;
    tfunc func;
    terr_proc err_proc;
    unsigned int timeout;
    const char *usage;
}titem;

/**
 * \the begining of item test in one module
 * \
 */
#define BEGIN_ITEM_MAP(module) \
    static const titem __item_map_##module[] = { \

/**
 * \the end of item test in one module
 * \add one item.
 */
#define END_ITEM_MAP(module) \
    {NULL,NULL,NULL,NULL,NULL} \
    };
/**
 * \define ADD_ITEM
 * \add one item.
 */
#define ADD_ITEM(name,func,err_proc,timeout,usage) \
        {#name,func,err_proc,timeout,usage},

/**
 * \define macro ITEM_MAP_POI
 * \get test item pointer.
 */
#define ITEM_MAP_POI(module) \
    ((titem *)(&__item_map_##module[0]))
 /**
 * \define macro GET_ITEM_MAP_POINTER
 * \get test item pointer.
 */
#define GET_ITEM_MAP_POINTER(module) \
    ((titem *)(&__item_map_##module[0]))
    
/**
 * \define struct tmodule
 * \indicate one test module.
 */    
typedef struct _tmodule{
    const char *name;
    titem *item_poi;
    tfunc func;
    terr_proc err_proc;
    unsigned int timeout;
    const char *usage;
}tmodule;

/**
 * \define ADD_MODULE
 * \add one module test.
 */ 
#define Module_Sec __attribute__((section(".sec_module")))
#define ADD_MODULE(name,item_poi,func,err_proc,timeout,usage) \
        tmodule _module_##name Module_Sec = {#name,item_poi,func,err_proc,timeout,usage}


extern int get_cmd(char *pstr);
extern void reset_argind(void);
extern char *get_argvalue(void);
extern int parse_args(int argc,char *argv[],const char *osi);

extern int exec_cmdline(const char *cmdline);
extern tmodule *find_module(const char *cmd);
extern titem *find_item(tmodule *module,const char *item_name);
extern int make_cmd(char *cmd,const char *name,const char *args,bool module);
#endif
